package com.un.ebs.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.un.ebs.core.exception.BusinessEntityNotFoundException;
import com.un.ebs.core.util.StringUtils;
import com.un.ebs.product.domain.*;
import com.un.ebs.product.dto.*;
import com.un.ebs.product.mapper.*;
import com.un.ebs.product.service.ProductClassAttrService;
import com.un.ebs.product.service.ProductClassService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author liubo
 * @since 2019-09-16
 */
@Service
public class ProductClassAttrServiceImpl extends ServiceImpl<ProductClassAttrMapper, ProductClassAttr> implements ProductClassAttrService {

    @Autowired
    private ProductClassMapper productClassMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ProductClassService productClassService;

    @Autowired
    private ProductClassAttrGroupMapper productClassAttrGroupMapper;

    @Autowired
    private ProductClassAttrValueMapper productClassAttrValueMapper;

    @CacheEvict(cacheNames = {"product_class_attr", "spu_attr_value"}, allEntries = true)
    @Override
    public void add(ProductClassAttrAddDto req) {
        ProductClassAttr obj = new ProductClassAttr();
        obj.setName(req.getName());
        obj.setClassId(req.getClassId());
        obj.setIsKey(req.getIsKey());
        obj.setIsMust(req.getIsMust());
        obj.setIsMulti(req.getIsMulti());
        obj.setIsSale(req.getIsSale());
        obj.setIsColumnShow(req.getIsColumnShow());
        obj.setIsDelete(false);
        obj.setSort(getBaseMapper().maxSort());
        obj.setGroupId(req.getGroupId());
        obj.insert();
    }

    @CacheEvict(cacheNames = {"product_class_attr", "spu_attr_value"}, allEntries = true)
    @Override
    public void update(ProductClassAttrUpdateDto req) {
        ProductClassAttr obj = getById(req.getId());
        obj.setName(req.getName());
        obj.setClassId(req.getClassId());
        obj.setIsKey(req.getIsKey());
        obj.setIsMust(req.getIsMust());
        obj.setIsMulti(req.getIsMulti());
        obj.setIsSale(req.getIsSale());
        obj.setIsColumnShow(req.getIsColumnShow());
        obj.setGroupId(req.getGroupId());
        obj.updateById();
    }

    @Override
    public ProductClassAttr queryById(String id) {
        return getBaseMapper().selectById(id);
    }

    @CacheEvict(cacheNames = {"product_class_attr", "spu_attr_value"}, allEntries = true)
    @Override
    public void delete(String id) {
        getBaseMapper().deleteById(id);
    }

    @CacheEvict(cacheNames = {"product_class_attr", "spu_attr_value"}, allEntries = true)
    @Override
    public void changeSort(String id, int index) {
        ProductClassAttr obj = getById(id);
        obj.setSort(index);
        getBaseMapper().updateById(obj);
    }

    @CacheEvict(cacheNames = {"product_class_attr", "spu_attr_value"}, allEntries = true)
    @Override
    public void changeSort(List<SortChangeDto> req) {
        for (SortChangeDto reqObj : req) {
            ProductClassAttr obj = getById(reqObj.getId());
            obj.setSort(reqObj.getIndex());
            getBaseMapper().updateById(obj);
        }
    }

    @Cacheable(cacheNames = "product_class_attr", key = "T(com.un.ebs.core.util.SecurityUtils).tenantId+'-ids-'+#classParentId")
    @Override
    public List<String> queryClassChildIds(String classParentId) {
        List<String> result = new ArrayList<>();

        LambdaQueryWrapper<ProductClass> childs = Wrappers.lambdaQuery();
        childs.eq(ProductClass::getParentId, classParentId);
        List<String> ids = productClassMapper.selectList(childs).stream().map(s -> s.getId()).collect(Collectors.toList());
        for (String id : ids) {
            result.add(id);
            result.addAll(queryClassChildIds(id));
        }
        return result;
    }

    @Cacheable(cacheNames = "product_class_attr", key = "'list-'+#classId")
    @Override
    public List<ProductClassAttr> queryByClassId(String classId) {
        List<String> ids = productClassService.queryParentIds(classId);
        LambdaQueryWrapper<ProductClassAttr> lq = Wrappers.lambdaQuery();
        lq.eq(ProductClassAttr::getIsDelete, false);
        lq.in(ProductClassAttr::getClassId, ids);
        lq.orderByAsc(ProductClassAttr::getSort);
        return baseMapper.selectList(lq);
    }

    @Cacheable(cacheNames = {"spu_attr_value"}, key = "#classId")
    @Override
    public List<ProductClassAttrVO> queryViewByClassId(String classId) {
        List<String> parentIds = productClassService.queryParentIds(classId);

        //查询属性分组
        LambdaQueryWrapper<ProductClassAttrGroup> lqGroup = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(parentIds)) {
            lqGroup.in(ProductClassAttrGroup::getClassId, parentIds);
        }
        lqGroup.eq(ProductClassAttrGroup::getIsDelete, false);
        List<ProductClassAttrGroup> groups = productClassAttrGroupMapper.selectList(lqGroup);

        //查询类别属性
        LambdaQueryWrapper<ProductClassAttr> lq = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(parentIds)) {
            lq.in(ProductClassAttr::getClassId, parentIds);
        }
        lq.eq(ProductClassAttr::getIsDelete, false);
        lq.orderByAsc(ProductClassAttr::getGroupId);
        lq.orderByAsc(ProductClassAttr::getSort);
        List<ProductClassAttr> attrs = baseMapper.selectList(lq);

        //查询类别属性值
        List<ProductClassAttrValue> values = new ArrayList<ProductClassAttrValue>();
        List<String> ids = attrs.stream().map(s -> s.getId()).collect(Collectors.toList());
        if (!StringUtils.isNullOrEmpty(ids)) {
            LambdaQueryWrapper<ProductClassAttrValue> query = Wrappers.lambdaQuery();
            query.in(ProductClassAttrValue::getClassAttrId, ids).
                    orderByAsc(ProductClassAttrValue::getSort);
            values = productClassAttrValueMapper.selectList(query);
        }

        List<ProductClassAttrVO> result = new ArrayList<>();
        for (ProductClassAttrGroup group : groups) {
            ProductClassAttrVO vo = new ProductClassAttrVO();
            vo.setGroupId(group.getId());
            vo.setGroupName(group.getGroupName());
            vo.setGroupSort(group.getSort());
            vo.setAttrs(new ArrayList<>());
            List<ProductClassAttr> groupAttr = attrs.stream().filter(s -> group.getId().equals(s.getGroupId())).collect(Collectors.toList());
            for (ProductClassAttr attr : groupAttr) {
                ProductClassAttrDto attrDto = new ProductClassAttrDto();
                attrDto.setId(attr.getId());
                attrDto.setClassId(attr.getClassId());
                attrDto.setGroupId(attr.getGroupId());
                attrDto.setName(attr.getName());
                attrDto.setIsKey(attr.getIsKey());
                attrDto.setIsMulti(attr.getIsMulti());
                attrDto.setIsMust(attr.getIsMust());
                attrDto.setIsSale(attr.getIsSale());
                attrDto.setIsColumnShow(attr.getIsColumnShow());
                attrDto.setIsDelete(attr.getIsDelete());
                attrDto.setTenantId(attr.getTenantId());
                attrDto.setCreateAt(attr.getCreateAt());
                attrDto.setCreateTime(attr.getCreateTime());
                attrDto.setLastModifiedAt(attr.getLastModifiedAt());
                attrDto.setLastModifiedTime(attr.getLastModifiedTime());
                attrDto.setValues(values.stream().filter(s -> s.getClassAttrId().equals(attr.getId())).collect(Collectors.toList()));
                vo.getAttrs().add(attrDto);
            }
            result.add(vo);
        }
        return result;
    }

    @Cacheable(cacheNames = "product_class_attr", key = "T(com.un.ebs.core.util.SecurityUtils).tenantId+'-spu-'+#productId")
    @Override
    public List<ProductClassAttr> queryByProductId(String productId) {
        Product product = productMapper.selectById(productId);
        if (product == null) {
            throw new BusinessEntityNotFoundException(productId, "SPU");
        }

        return queryByClassId(product.getClassId());

    }
}